<?php
declare (strict_types=1);

namespace app\index\controller;

use app\BaseController;
use app\index\model\UsersModel;
use think\Exception;
use think\facade\Log;

class Base extends BaseController
{

    /**
     * 执行curl请求
     * @param $url
     * @param $params
     * @param string $method
     * @param array $header
     * @param bool $multi
     * @return bool|string
     * @throws Exception
     */
    public function httpCurl($url, $params = [], $method = 'GET', $header = array(), $multi = false)
    {
        date_default_timezone_set('PRC');
        $opts = [
            CURLOPT_TIMEOUT => 30,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER => $header,
            CURLOPT_COOKIESESSION => true,
            CURLOPT_FOLLOWLOCATION => 1,
            CURLOPT_COOKIE => session_name() . '=' . session_id(),
        ];

        // 根据请求类型设置特定参数
        switch (strtoupper($method)) {
            case 'GET':
                // $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
                // 链接后拼接参数  &  非？
                $opts[CURLOPT_URL] = $params ? $url . '?' . http_build_query($params) : $url;
                break;

            // 判断是否传输文件
            case 'POST':
                $params = $multi ? $params : (is_string($params) ? $params : http_build_query($params));
                $opts[CURLOPT_URL] = $url;
                $opts[CURLOPT_POST] = 1;
                $opts[CURLOPT_POSTFIELDS] = $params;
                break;

            default:
                throw new Exception('不支持的请求方式！');
        }

        // 初始化
        $ch = curl_init();
        // 批量传输curl设置
        curl_setopt_array($ch, $opts);
        // 执行curl请求
        $data = curl_exec($ch);
        // 返回curl最后一次的错误信息，如果没有则返回空字符串
        $error = curl_error($ch);
        // 关闭curl请求
        curl_close($ch);

        if ($error) throw new Exception('请求发生错误：' . $error);

        return $data;
    }


    /**
     * 微信信息解密
     * @param string $appid 小程序id
     * @param string $sessionKey 小程序密钥
     * @param string $encryptedData 在小程序中获取的encryptedData
     * @param string $iv 在小程序中获取的iv
     * @return array 解密后的数组
     */
    public function decryptData($appid, $sessionKey, $encryptedData, $iv)
    {
        $OK = 0;
        $IllegalAesKey = -41001;
        $IllegalIv = -41002;
        $IllegalBuffer = -41003;
        $DecodeBase64Error = -41004;

        if (strlen($sessionKey) != 24) {
            return $IllegalAesKey;
        }
        $aesKey = base64_decode($sessionKey);

        if (strlen($iv) != 24) {
            return $IllegalIv;
        }
        $aesIV = base64_decode($iv);

        $aesCipher = base64_decode($encryptedData);

        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
        $dataObj = json_decode($result);
        if ($dataObj == NULL) {
            return $IllegalBuffer;
        }
        if ($dataObj->watermark->appid != $appid) {
            return $DecodeBase64Error;
        }
        $data = json_decode($result, true);

        return $data;
    }

    /**
     * 请求过程中因为编码原因+号变成了空格
     * 需要用下面的方法转换回来
     */
    public function define_str_replace($data)
    {
        return str_replace(' ', '+', $data);

    }

    /**
     * 检测用户是否登录
     * @return array|\think\Model|\think\response\Json|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function checkLogin()
    {
        Log::write('开始checkLogin:' . json_encode($this->request->param()), 'error');
        // 仅作为测试
        if ($this->request->header('ts')) {
            $info = UsersModel::getUserInfo(['id'=>25]);
            return $info;
        }
        if ($_SERVER['REMOTE_ADDR'] == '127.0.0.1') {
            return true;
        }
        $type = $this->request->header('type');
        Log::write('checkLogin type:' . json_encode($type), 'error');
        if (!isset($type)) {
            $this->responseJson(10502, '登录方式有误');
        }
        // 登录端标识：0小程序 1公众号
        switch ($type) {
            case 0:
                $token = $this->request->header('token');
                $loginType = '小程序';
                $where = ['token' => $token];
                break;
            case 1:
                $token = $this->request->header('token1');
                $loginType = '公众号';
                $where = ['token1' => $token];
                break;
            default:
                $token = '';
                $loginType = '未知';
                $where = [];
        }
        Log::write(''.$loginType.'checkLogin token:' . json_encode($token), 'error');
        if (!$token) {
            $this->responseJson(10502, '请先登录');
        }

        Log::write(''.$loginType.'checkLogin where:' . json_encode($where), 'error');
        // 查询账号信息
        $info = UsersModel::getUserInfo($where);
        Log::write(''.$loginType.'checkLogin userInfo:' . json_encode($info), 'error');
        if (empty($info)) {
            Log::write('账号不存在' . json_encode($info), 'error');
            $this->responseJson(10502, '账号不存在');
        }
        if ($info['state'] == 0) {
            Log::write('当前账号被禁用' . json_encode($info), 'error');
            $this->responseJson(10502, '当前账号被禁用');
        }

        return $info;
    }

    /**
     * json 返回
     * @param $code
     * @param $msg
     * @param array $data
     */
    public function responseJson($code, $msg, $data = [])
    {
        // 记录请求信息
        Log::write('请求来源路径：' . $_SERVER['REQUEST_URI'] . '，参数：' . json_encode($this->request->param()), 'error');

        $json = json_encode([
            'code' => $code,
            'msg' => $msg,
            'data' => $data,
        ]);
        exit($json);
    }
}